﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using SharpShare.Configuration;
using SharpShare.Afp.Protocol.Security;
using System.Net;
using System.ComponentModel;

namespace SharpShare.Afp.Configuration {
    public class AfpServiceConfigurationElement : ServiceElement<AfpShareConfigurationElement> {
        [Category("Security")]
        [DisplayName("User Authentication Methods")]
        [Description("The enabled user authentication methods (UAMs).")]
        [TypeConverter(typeof(AfpUamTypesConverter))]
        [ConfigurationProperty("authenticationMethods")]
        public AfpUamConfigurationElementCollection AuthenticationMethods {
            get {
                return (AfpUamConfigurationElementCollection)this["authenticationMethods"];
            }
            set {
                this["authenticationMethods"] = value;
            }
        }

        [ConfigurationProperty("authentication")]
        public AuthenticationElement Authentication {
            get {
                return (AuthenticationElement)this["authentication"];
            }
            set {
                this["authentication"] = value;
            }
        }

        [Category("Advanced")]
        [DisplayName("Machine Type")]
        [Description("The machine type string reported to AFP clients. On Mac OS X, this value is typically used to determine the icon to display for the server.")]
        [ConfigurationProperty("machineType", DefaultValue = AfpServerSettings.DefaultMachineType)]
        public string MachineType {
            get {
                return (string)this["machineType"];
            }
            set {
                this["machineType"] = value;
            }
        }

        [Category("Connection")]
        [Description("The TCP port to listen for incoming connections on. Default is 548. Specify 0 to use a random port.")]
        [ConfigurationProperty("port", DefaultValue = AfpServerSettings.DefaultAfpPort)]
        public int Port {
            get {
                return (int)this["port"];
            }
            set {
                this["port"] = value;
            }
        }

        [Category("Connection")]
        [DisplayName("Binding Address")]
        [Description("The IP address to bind the listening socket. Empty indicates any IP address (0.0.0.0).")]
        [ConfigurationProperty("bindAddress")]
        public string BindAddress {
            get {
                return (string)this["bindAddress"];
            }
            set {
                this["bindAddress"] = value;
            }
        }

        [Category("Advanced")]
        [DisplayName("Request Quanta")]
        [Description("The maximum number of bytes the server can accept per request.")]
        [ConfigurationProperty("requestQuanta", DefaultValue = AfpServerSettings.DefaultRequestQuanta)]
        [TypeConverter(typeof(BytesTypeConverter))]
        public int RequestQuanta {
            get {
                return (int)this["requestQuanta"];
            }
            set {
                this["requestQuanta"] = value;
            }
        }

        [Category("Advanced")]
        [DisplayName("Server Signature")]
        [Description("The server signature reported to AFP clients. Leave blank to auto-generate from the local machine's name.")]
        [ConfigurationProperty("serverSignature")]
        public string ServerSignature {
            get {
                return (string)this["serverSignature"];
            }
            set {
                this["serverSignature"] = value;
            }
        }

        public override IShareService CreateService(IConfigurationContext context) {
            AfpServerSettings settings = new AfpServerSettings() {
                Port = this.Port,
                MachineType = this.MachineType,
                RequestQuanta = this.RequestQuanta,
                UserManager = this.Authentication
            };

            IPAddress bindAddress;
            if (IPAddress.TryParse(this.BindAddress, out bindAddress)) {
                settings.Binding = bindAddress;
            }

            if (this.AuthenticationMethods.Count > 0) {
                settings.AuthenticationMethods.Clear();
                foreach (IAfpUserAuthenticationMethod method in this.AuthenticationMethods.Cast<AfpUamConfigurationElement>().Select(m => m.Create())) {
                    settings.AuthenticationMethods.Add(method);
                }
            }

            Afp.AfpShareServer server = new Afp.AfpShareServer(this.Name, settings);

            return server;
        }
    }


}
